/*
 * NetVisualize.java
 *
 * Created on January 8, 2010, 7:34 PM
 */

package networkvisualize;


import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.math.MathContext;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.awt.Point;
import javax.swing.*;
import java.io.*;
import java.net.*;
import java.awt.event.KeyEvent;
import java.util.Timer;
import java.util.TimerTask;

/**
 *
 * @author  hrushi
 */
public class NetVisualize extends javax.swing.JFrame {

    public static int MAX_NUM_NODES_DISPLAY = 50;
    //public static String logPath = "./../../tools/raw/detailed_distance_log";  // with NetBeans
    //public static String statPath = "./../../tools/raw/statlist_refined"; // with NetBeans
    //public static String hostPath = "./../../config/hosts"; // with NetBeans
    
    public static String logPath = "./../../../tools/raw/detailed_distance_log"; // with cmdline
    public static String statPath = "./../../../tools/raw/statlist_refined"; // with cmdline
    public static String hostPath = "./../../../config/hosts"; // with cmdline
    
    public static int FRAME_WIDTH = 800;
    public static int FRAME_HEIGHT = 300;
    public static int FILE_BUF_LENGTH = 100;
    public static int FILE_BUF_LENGTH2 = 100;
    public static int NODE_RADIUS = 10;
    public static int WIDE_ANGLE = 60;

    Node[] node;
    RefreshThread rThread;
    Timer timer;
    int numNodes=0;
    int paintFlag = 0;
    
    /** Creates new form NetVisualize */
    public NetVisualize() {
        timer = new Timer();
        initComponents();
        
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                formMouseClicked(evt);
            }
        });
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowActivated(java.awt.event.WindowEvent evt) {
                formWindowActivated(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

private void formMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseClicked
// TODO add your handling code here:
    Point p = evt.getPoint();
        
    for (int i=0; i<=numNodes; i++) {
        int distance = (int)Point.distance(p.x, p.y, node[i].x + NODE_RADIUS, node[i].y + NODE_RADIUS);
        //System.out.println(p.x + "," + p.y + "," + node[i].x + "," + node[i].y);
        System.out.println("dist" +distance);        
        if (distance < NODE_RADIUS) {
            System.out.println("Clicked inside circle");
            NodeStatistics nStats = new NodeStatistics();
            nStats.setLabelMac(node[i].mac);
            nStats.setLabelDist(String.valueOf(node[i].dist));
            nStats.setTitle("Node Statistics");
            nStats.setLocation((p.x + 2*NODE_RADIUS), (p.y + 2*NODE_RADIUS));
            nStats.add_data();
            nStats.setVisible(true);
            //this.repaint();
        }
    }
}//GEN-LAST:event_formMouseClicked

private void formWindowActivated(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowActivated
// TODO add your handling code here:
    timer.scheduleAtFixedRate(new TimerTask() { public void run() { repaint(); } } ,0, 5000);
}//GEN-LAST:event_formWindowActivated

    public void paint (Graphics g) {

        Graphics2D g2 = (Graphics2D) g;
        System.out.println("Inside paint");
//        g.setColor(Color.GRAY);

        g.clearRect(0, 0, FRAME_WIDTH, FRAME_HEIGHT);
        this.setBounds(0, 0, FRAME_WIDTH, FRAME_HEIGHT);
        
        FileHandler fhRead = new FileHandler(hostPath);
        String[] strArr1, strSplit1, strArr2, strSplit2, strDist = null;
        String myName = "", myMac = "", myIP = "";
        node = new Node[MAX_NUM_NODES_DISPLAY];
        int nodeCnt = 0;
        int strMacCnt = 0;
        
        if (fhRead.openFile(0)) {
            strArr1 = fhRead.readIntoArray(); 
            fhRead.closeFile();
            
            StringBuffer sb = new StringBuffer(512);
            try 
            {
                String cm = "cat /proc/distance";
                InputStream in = Runtime.getRuntime().exec(cm).getInputStream();
                int ch;
                while ( ( ch = in.read() ) != -1 ) {	
                    sb.append((char) ch); 
                }
                strArr2 = sb.toString().split("\n");
                System.out.println("arr2 " + strArr2.length);
                //nodeCnt = strArr1.length;
                for (int i=0; i<strArr1.length; i++) {
                    strSplit1 = strArr1[i].split(" ");
                    if (strSplit1[2].trim().equals(strSplit1[3].trim())) {
                        node[i] = new Node();
                        node[i].ip = strSplit1[1];
                        node[i].mac = strSplit1[2];
                        node[i].name = strSplit1[0];
                        node[i].dist = 0;
                        System.out.println(i + ":" + node[i].name + " " + node[i].dist);
                    }
                    else {
                        for (int j=0; j<strArr2.length; j++) {
                            strSplit2 = strArr2[j].split(" ");
                            if (strSplit2.length > 2) {
                                if (strSplit1[2].trim().equals(strSplit2[7].trim())) {
                                    node[i] = new Node();
                                    node[i].ip = strSplit1[1];
                                    node[i].mac = strSplit1[2];
                                    node[i].name = strSplit1[0];
                                    node[i].dist = Integer.parseInt(strSplit2[10]);
                                    System.out.println(i + ":" + node[i].name + " " + node[i].dist);
                                    break;
                                }
                            }
                        }
                    }

                }
            }catch (IOException e) {
                System.out.println ("/proc/distance not opening");
                return;
            }catch (ArrayIndexOutOfBoundsException exc) {
                System.out.println ("array outof bounds exc in paint");
                return;
            }
            

            for (int i=0; i<strArr1.length; i++) {
                for (int j=i+1; j<strArr1.length; j++) {
                    if (node[j].dist < node[j-1].dist) {
                        Node temp = new Node();
                        temp = node[j-1];
                        node[j-1] = node[j];
                        node[j] = temp;
                    }
                }
            }
            
            numNodes = nodeCnt = strArr1.length-1;
            
            
            int xDiff = this.getWidth()/(nodeCnt+2);
            g.setColor(Color.DARK_GRAY);
            g.fillOval((int)xDiff-NODE_RADIUS, this.getHeight()/2-NODE_RADIUS, NODE_RADIUS*2, NODE_RADIUS*2);
            Font font = new Font("Courier", Font.BOLD,  10);
            g.setFont(font);
            g.drawString("Me (" + node[0].name + ")", xDiff - NODE_RADIUS*10, this.getHeight()/2);
            node[0].x = (int)xDiff-NODE_RADIUS;
            node[0].y = this.getHeight()/2-NODE_RADIUS;
            int x1 = (int)xDiff;
            int y1 = this.getHeight()/2;
            
            float diffAngle = 0, startAngle = 0;
            float diffLen = 200, startLen = 200;

            if (nodeCnt > 1) {
                diffAngle = WIDE_ANGLE / (nodeCnt-1);
                startAngle = -(WIDE_ANGLE/2);
                diffLen = 200 / (nodeCnt-1);
                startLen = 200;
            }



            float len = startLen;
            int xStart = xDiff, yStart = this.getHeight()/2;
                        
            
            for (int i=1; i<=nodeCnt; i++) {
                
                int x = (int)(len * Math.cos(startAngle/360));
                int y = (int)(len * Math.sin(startAngle/360));
                System.out.println(x + "," + y + "," + startAngle);
                g.fillOval(xStart + x - NODE_RADIUS, yStart + y - NODE_RADIUS, NODE_RADIUS*2, NODE_RADIUS*2);
                node[i].x = (int)(xStart + x - NODE_RADIUS);
                node[i].y = (int)(yStart + y - NODE_RADIUS);
                g.drawLine(x1, y1, node[i].x + NODE_RADIUS, node[i].y + NODE_RADIUS);
                g.drawString(node[i].name, node[i].x+NODE_RADIUS*3, node[i].y + (int)(NODE_RADIUS*1));
                len += diffLen;
                startAngle += diffAngle;
            }
             
            
        }
        else {
            System.out.println ("hosts file not opening");
            g.setColor(Color.DARK_GRAY);
            Font font = new Font("Courier", Font.BOLD,  20);
            g.setFont(font);
            g.drawString("Network inactive", 100, 100);
        }
            
        /*
        for (int i = (strArr1.length - 1); i > 0 && (strArr1.length - 1 - i) < FILE_BUF_LENGTH; i--)  {
            String[] strArr2 = strArr1[i].split(" "); // used to split lines in strArr1

            if (strArr2[0].trim().equals("distance")) {
                //System.out.println("i = " + i + "mac = " + strArr2[1]);
                int foundFlag = 0, j;
                if (nodeCnt > 0) {
                    for (j=0; j<nodeCnt; j++) {
                        //System.out.println("j = " + j + " mac " + node[j].mac);
                        if (node[j].mac.trim().equals(strArr2[1].trim())) {
                            node[j].dist = Integer.parseInt(strArr2[2]);
                            foundFlag = 1;
                            break;
                        }
                    }
                }
                if (foundFlag==0) {
                  //  System.out.println(strArr2[1] + " " + Integer.parseInt(strArr2[2]) + " at " + nodeCnt);
                    node[nodeCnt] = new Node();
                    node[nodeCnt].mac = strArr2[1];
                    node[nodeCnt].dist = Integer.parseInt(strArr2[2]);
                    System.out.println("Adding " + node[nodeCnt].mac + " " + node[nodeCnt].dist);
                    nodeCnt++;
                }
            }
        }

        Node temp = new Node();
        for (int i=0; i<nodeCnt; i++) {
            for (int j=0; j<i; j++) {
                if (node[j].dist > node[i].dist) {
                    temp = node[j];
                    node[j] = node[i];
                    node[i] = temp;
                }
            }
        }

        System.out.println("Adding over " + nodeCnt);
        this.setBounds(0, 0, FRAME_WIDTH, FRAME_HEIGHT);
        int xDiff = this.getWidth()/(nodeCnt+2);
        System.out.println("strMAC: " + strMacCnt + ", xDiff " + xDiff);
        g.fillOval((int)xDiff-NODE_RADIUS, this.getHeight()/2-NODE_RADIUS, NODE_RADIUS*2, NODE_RADIUS*2);
        g.setColor(Color.DARK_GRAY);
        g.drawString("Me", xDiff - NODE_RADIUS*4, this.getHeight()/2);
        g.setColor(Color.GRAY);
        int x1 = (int)xDiff;
        int y1 = this.getHeight()/2;

        float diffAngle = 0, startAngle = 0;
        float diffLen = 200, startLen = 200;
        
        if (nodeCnt > 1) {
            diffAngle = WIDE_ANGLE / (nodeCnt-1);
            startAngle = -(WIDE_ANGLE/2);
            diffLen = 200 / (nodeCnt-1);
            startLen = 200;
        }
        
        

        float len = startLen;
        int xStart = xDiff, yStart = this.getHeight()/2;
        Font font = new Font("Courier", Font.BOLD,  10);
        g.setFont(font);
        for (int i=0; i<nodeCnt; i++) {
            
            int x = (int)(len * Math.cos(startAngle/360));
            int y = (int)(len * Math.sin(startAngle/360));
            System.out.println(x + "," + y + "," + startAngle);
            g.fillOval(xStart + x - NODE_RADIUS, yStart + y - NODE_RADIUS, NODE_RADIUS*2, NODE_RADIUS*2);
            node[i].x = (int)(xStart + x - NODE_RADIUS);
            node[i].y = (int)(yStart + y - NODE_RADIUS);
            g.drawLine(x1, y1, node[i].x + NODE_RADIUS, node[i].y + NODE_RADIUS);
            g.drawString(node[i].mac, node[i].x+NODE_RADIUS*3, node[i].y + (int)(NODE_RADIUS*1));
            len += diffLen;
            startAngle += diffAngle;
            
        }

        fhRead = new FileHandler(nameList);
        fhRead.openFile(0);
        strArr1 = fhRead.readIntoArray();
        fhRead.closeFile();
        g.setColor(Color.DARK_GRAY);
        for (int i=0; i<nodeCnt; i++) {
            //for (int j=0; j<strArr1.length; j++) {
                //String[] strArr2 = strArr1[j].split(" ");
              //  if (node[i].mac.trim().equals(strArr2[0])) {
                //    System.out.println(strArr2[1]);
                    //g.drawString(strArr2[1], node[i].x + NODE_RADIUS*3, node[i].y + NODE_RADIUS);
                    //g.drawString(node[i].mac, node[i].x + NODE_RADIUS*3, node[i].y + (int)(NODE_RADIUS*1.5));
              //  }
            //}
        }

        numNodes = nodeCnt;
        paintFlag = 1;
         */

    }


    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables

}
